Using File Objects
You use file objects to read 3DMF data from or write 3DMF data to a storage object, which represents a physical storage device available on a computer. Before you can access 3DMF data in a piece of storage, however, you need to create a storage object to represent the physical storage device, create a file object, and attach the file object to the storage object. This section describes how to perform these tasks.Creating a File Object
To access the data in a piece of storage that conforms to the 3DMF standard (such as a file on disk or a block of memory on the Clipboard), you need to create a new storage object, create a new file object, and attach the file object to the storage object. Thereafter, you can open the file object and read the data in it or write data to it. Listing 17-1 illustrates how to create storage and file objects and attach them to one another.The
MyGetInputFile
function defined in Listing 17-1 calls the application-
defined routineMyGetInputFileName
to get the name of the disk file to open. Then it callsQ3FSSpecStorage_New
to create a new storage object associated with that disk file andQ3File_New
to create a new file object. If both creation calls complete successfully,MyGetInputFile
callsQ3File_SetStorage
to attach the file object to the storage object.
Listing 17-1 Creating a new file object
- Note
- See the chapter "Storage Objects" for complete
details on creating storage objects.![]()
TQ3FileObject MyGetInputFile (void) { TQ3FileObject myFileObj; TQ3StorageObject myStorageObj; FSSpec myFSSpec; if (MyGetInputFileName(&myFSSpec) == kQ3False) return(NULL); /*Create new storage object and new file object.*/ if(((myStorageObj = Q3FSSpecStorage_New(&myFSSpec)) == NULL) || ((myFileObj = Q3File_New()) == NULL)) { if (myStorageObj) Q3Object_Dispose(myStorageObj); return(NULL); } /*Set the storage for the file object.*/ Q3File_SetStorage(myFileObj, myStorageObj); Q3Object_Dispose(myStorageObj); return (myFileObj); }Notice that the call toQ3File_SetStorage
is followed immediately by a call toQ3Object_Dispose
. The call toQ3File_SetStorage
increases the reference count of the storage object, and the call toQ3Object_Dispose
simply decreases that count.Reading Data from a File Object
The data in an 3DMF file is organized into discrete units called metafile objects (or, more briefly, and despite the risk of confusion with QuickDraw 3D objects, objects). You read data from an 3DMF file by reading each individual metafile object in it (by calling theQ3File_ReadObject
function), until you reach the end of the file. Listing 17-2 illustrates how to read the metafile objects in an 3DMF file.The
My
Read3DMFModel function defined in Listing 17-2 opens a file object and sequentially reads each metafile object in the 3DMF file into a QuickDraw 3D object.My
Read3DMFModel determines the type of the QuickDraw 3D object read. If the object is a view hints object,My
Read3DMFModel returns that object in theviewHints
parameter. If the object isn't a view object, it must be some other drawable QuickDraw 3D object. In that case,My
Read3DMFModel either returns that object in themodel
parameter (if there are no more objects in the 3DMF file) or adds it to a display group. When it executes successfully,My
Read3DMFModel returns both a 3D model and a view hints object to its caller.Listing 17-2 Reading metafile objects
TQ3Status MyRead3DMFModel (TQ3FileObject file, TQ3Object *model, TQ3Object *viewHints) { TQ3Object myGroup; TQ3Object myObject; /*Initialize view hints and model to be returned.*/ *viewHints = NULL; *model = NULL; myGroup = NULL; myObject = NULL; /*Open the file object and exit gracefully if unsuccessful.*/ if (Q3File_OpenRead(file, NULL) != kQ3Success) { DoError("MyRead3DMFModel", "Reading failed %s", filename); return kQ3Failure; } while (Q3File_IsEndOfFile(file) == kQ3False) { myObject = NULL; /*Read a metafile object from the file object.*/ myObject = Q3File_ReadObject(file); if (myObject == NULL) continue; /*Save a view hints object, and add any drawable objects to a group.*/ if (Q3Object_IsType(myObject, kQ3SharedTypeViewHints)) { if (*viewHints == NULL) { *viewHints = myObject; myObject = NULL; } } else if (Q3Object_IsDrawable(myObject)) { if (myGroup) { Q3Group_AddObject(myGroup, myObject); } else if (*model == NULL) { *model = myObject; myObject = NULL; } else { myGroup = Q3DisplayGroup_New(); Q3Group_AddObject(myGroup, *model); Q3Group_AddObject(myGroup, myObject); Q3Object_Dispose(*model); *model = myGroup; } } if (myObject != NULL) Q3Object_Dispose(myObject); } if (Q3Error_Get(NULL) != kQ3ErrorNone) { if (*model != NULL) { Q3Object_Dispose(*model); *model = NULL; } if (*viewHints != NULL) { Q3Object_Dispose(*viewHints); *viewHints = NULL; } return (kQ3Failure); } return kQ3Success; }Writing Data to a File Object
To write a model or other 3D data into a file conforming to the QuickDraw 3D Object Metafile format, you can use submit calls (such asQ3Object_Submit
) with an open file object that is attached to a storage object. Depending on the complexity of the model and the amount of available memory, QuickDraw 3D might need to traverse the model more than once to write the data to the target physical storage device. Accordingly, you should perform all write operations within a writing loop, bracketed by calls toQ3View_StartWriting
andQ3View_EndWriting
. Listing 17-3 illustrates a simple writing loop.Listing 17-3 Writing 3D data to a file object
Q3View_StartWriting(myView, myFileObj); do { Q3Object_Submit(myModel, myView); Q3Polyline_Submit(&myAnimatedData, myView); Q3TriGrid_Submit(&myBumpExtrapolationGrid, myView); } while (Q3View_EndWriting(myView) == kQ3ViewStatusRetraverse);